/**
 * Truenewx 依赖库
 */
import tnx from '@/tnx.js';
import DependencyLib from '../entity/DependencyLib.js';
import DependencyLibType from '../enums/DependencyLibType.js';
import TypeKind from '../enums/TypeKind.js';
import ParseUtil from './parse.js';

const tnxjee26CoreLib = new DependencyLib(DependencyLibType.TRUENEWX);
const tnxjee26ModelLib = new DependencyLib(DependencyLibType.TRUENEWX);
const tnxjee26RepoJpaLib = new DependencyLib(DependencyLibType.TRUENEWX);

const tnxjee30CoreLib = new DependencyLib(DependencyLibType.TRUENEWX);
const tnxjee30ModelLib = new DependencyLib(DependencyLibType.TRUENEWX);
const tnxjee30RepoJpaLib = new DependencyLib(DependencyLibType.TRUENEWX);

const tnxjee34CoreLib = new DependencyLib(DependencyLibType.TRUENEWX);
const tnxjee34ModelLib = new DependencyLib(DependencyLibType.TRUENEWX);
const tnxjee34RepoJpaLib = new DependencyLib(DependencyLibType.TRUENEWX);

const root = tnx.app.getRoot();

const tnxjeeCorePredicate = function (packageName) {
    return ['org.truenewx.tnxjee.core.spec', 'org.truenewx.tnxjee.core.util',
        'org.truenewx.tnxjee.core.util.tuple'].includes(packageName);
}

const tnxjeeModelPredicate = function (packageName) {
    return ['org.truenewx.tnxjee.model.query'].includes(packageName)
        || packageName.startsWith('org.truenewx.tnxjee.model.spec');
}

export default {
    loadModels(version, callback) {
        if (version.startsWith('2.')) {
            ParseUtil.loadByCodeJar(tnxjee26CoreLib, root + '/resources/tnxjee-core-2.6-sources.jar',
                tnxjeeCorePredicate, () => {
                    ParseUtil.loadByCodeJar(tnxjee26ModelLib, root + '/resources/tnxjee-model-2.6-sources.jar',
                        tnxjeeModelPredicate, () => {
                            callback([tnxjee26CoreLib, tnxjee26ModelLib]);
                        });
                });
        } else if (version.startsWith('3.0.')) {
            ParseUtil.loadByCodeJar(tnxjee30CoreLib, root + '/resources/tnxjee-core-3.0-sources.jar',
                tnxjeeCorePredicate, () => {
                    ParseUtil.loadByCodeJar(tnxjee30ModelLib, root + '/resources/tnxjee-model-3.0-sources.jar',
                        tnxjeeModelPredicate, () => {
                            callback([tnxjee30CoreLib, tnxjee30ModelLib]);
                        });
                });
        } else if (version.startsWith('3.4.')) {
            ParseUtil.loadByCodeJar(tnxjee34CoreLib, root + '/resources/tnxjee-core-3.4-sources.jar',
                tnxjeeCorePredicate, () => {
                    ParseUtil.loadByCodeJar(tnxjee34ModelLib, root + '/resources/tnxjee-model-3.4-sources.jar',
                        tnxjeeModelPredicate, () => {
                            callback([tnxjee34CoreLib, tnxjee34ModelLib]);
                        });
                });
        }
    },
    loadConverters(version, callback) {
        let time0 = new Date().getTime();
        const loadRepoJpaConverters = function (lib, path, maxRetryNum) {
            if (maxRetryNum === undefined && lib.initialized === null) {
                console.info(`${path} 开始解析转换器类...`);
            }
            ParseUtil.loadByCodeJar(lib, path,
                packageName => packageName.startsWith('org.truenewx.tnxjee.repo.jpa.converter'),
                () => {
                    maxRetryNum = maxRetryNum || lib.classes.length;
                    let retryNum = 0;
                    for (let i = lib.classes.length - 1; i >= 0; i--) {
                        let origin = lib.classes[i].origin;
                        if (!TypeKind.CONVERTER.equals(origin.kind)) {
                            lib.classes.splice(i, 1);
                            retryNum++;
                        }
                    }
                    if (0 < retryNum && retryNum < maxRetryNum) {
                        setTimeout(() => {
                            lib.initialized = null;
                            loadRepoJpaConverters(lib, path, retryNum);
                        });
                    } else if (lib.initialized) {
                        // 最终去掉抽象或找不到逻辑类型的转换器
                        for (let i = lib.classes.length - 1; i >= 0; i--) {
                            let origin = lib.classes[i].origin;
                            if (origin.abstractClass || !origin.logicType) {
                                lib.classes.splice(i, 1);
                            } else {
                                // console.info(`${origin.getName()}<${origin.logicType}>`);
                            }
                        }
                        if (typeof callback === 'function') {
                            callback(lib);
                        } else {
                            let time1 = new Date().getTime();
                            let dTime = time1 - time0;
                            if (dTime > 0) {
                                console.info(`${path} 最终取得 ${lib.classes.length} 个转换器类，总耗时：${dTime}ms`);
                            }
                        }
                    }
                }, false);
        }
        if (version.startsWith('2.')) {
            loadRepoJpaConverters(tnxjee26RepoJpaLib, root + '/resources/tnxjee-repo-jpa-2.6-sources.jar');
        } else if (version.startsWith('3.0.')) {
            loadRepoJpaConverters(tnxjee30RepoJpaLib, root + '/resources/tnxjee-repo-jpa-3.0-sources.jar');
        } else if (version.startsWith('3.4.')) {
            loadRepoJpaConverters(tnxjee34RepoJpaLib, root + '/resources/tnxjee-repo-jpa-3.4-sources.jar');
        }
    },
};
